package com.mh.system.service.impl;

import com.mh.common.constant.Constants;
import com.mh.common.core.exception.UidPwdNotMatchException;
import com.mh.common.utils.RedisCache;
import com.mh.common.core.exception.CaptchaException;
import com.mh.system.domain.LoginUserDetails;
import com.mh.system.domain.vo.LoginBody;
import com.mh.system.service.SysLoginService;
import com.mh.system.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Service;

@Service
public class SysLoginServiceImpl implements SysLoginService {

    @Autowired
    private RedisCache redisCache;

    //Security配置类中已经加上@Bean
    @Autowired
    private AuthenticationManager authManager;

    @Autowired
    private TokenService tokenService;

    //带验证码登录验证
    @Override
    public String login(LoginBody loginBody) {
        //1. 验证码校验
        //1.1 传入key值,从Redis中取出value(验证码)
        String key = Constants.CAPTCHA_CODE_KEY + loginBody.getUuid();
        System.out.println("前端传入uuid: "+key);
        String value = redisCache.getCacheObject(key);
        System.out.println("验证码是: "+value);
        //1.2 取出value后在Redis中删除数据
        redisCache.deleteObject(key);
        //1.3 异常处理
        //redis中取出的验证码为空,或者前端传入的验证码 ≠ Redis的验证码 --> 抛出异常
        if (value == null || !loginBody.getCode().equals(value)) {
            throw new CaptchaException(); //抛出自定义的验证码校验异常
        }

        //2. 用户认证 --> 认证通过返回完整的Authentication对象,否则抛异常
        //2.1 需要通过AuthenticationManager的authenticate()认证,因此注入对象
        //authenticate()方法需要传入Authentication对象
        //UsernamePasswordAuthenticationToken传入用户名&密码,返回Authentication对象
        Authentication auth = null;
        //2.2 有认证未通过可能性,因此用try-catch捕获异常
        try {
            auth = authManager.authenticate
                    (new UsernamePasswordAuthenticationToken
                    (loginBody.getUsername(), loginBody.getPassword()));
        } catch (AuthenticationException e) {
            throw new UidPwdNotMatchException();
        }

        //3. Authentication对象中获取主体,返回UserDetails对象
        //在此模块中由LoginUserDetails实现了UserDetails接口,因此返回结果由它接收
        LoginUserDetails loginUser = (LoginUserDetails) auth.getPrincipal();
        System.out.println("用户名是: "+loginUser);
        //4. 生成Token
        return tokenService.createToken(loginUser);
    }
}
